package com.zmn.oms.dubbo.impl.normal.master;

import com.alibaba.fastjson.JSON;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.oms.business.interfaces.mastercontact.OrderMasterContactBService;
import com.zmn.oms.business.interfaces.work.OrderWorkProgrammeBService;
import com.zmn.oms.common.constant.AppConsts;
import com.zmn.oms.common.constant.OrderPayConsts;
import com.zmn.oms.common.dio.OmsAppBaseDIO;
import com.zmn.oms.common.dio.normal.master.CancelConfirmDIO;
import com.zmn.oms.common.dio.normal.master.GrabOrderDIO;
import com.zmn.oms.common.dio.normal.master.ReworkRefundDIO;
import com.zmn.oms.common.dio.normal.master.UpdateAddressDIO;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.dubbo.dto.common.work.ContactUserDIO;
import com.zmn.oms.dubbo.interfaces.normal.master.MasterOrderWorkModifyRemoteService;
import com.zmn.oms.dubbo.utils.DubboConsts;
import com.zmn.oms.model.dto.graborder.GrabOrderWorkDTO;
import com.zmn.oms.model.dto.work.masterwork.CancelConfirmDTO;
import com.zmn.oms.model.dto.work.masterwork.CompleteDTO;
import com.zmn.oms.model.dto.work.masterwork.ContactUserDTO;
import com.zmn.oms.model.entity.pay.OrderPay;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.services.interfaces.pay.OrderPayService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.services.interfaces.work.masterwork.MasterWorkService;
import com.zmn.oms.zmn.business.interfaces.refund.ZsRefundBService;
import com.zmn.oms.zmn.business.interfaces.rework.ZsReworkBService;
import com.zmn.oms.zmn.business.interfaces.work.OrderWorkGrabBService;
import com.zmn.oms.zmn.business.interfaces.work.autoflow.WorkFlowContextBService;
import com.zmn.oms.zmn.business.interfaces.work.masterwork.ZsMasterWorkBService;
import com.zmn.oms.zmn.normal.business.interfaces.order.ZsNormalOrderBService;
import com.zmn.oms.zmn.normal.business.interfaces.work.masterwork.ZsNormalMasterWorkBService;
import com.zmn.pay.common.constant.PayConsts;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;

import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 类描述：
 *
 * @author wangxiaokun
 * @since 2021/07/15 16:21
 */
@Slf4j
@Service(loadbalance = "roundrobin", timeout = 90000, retries = 2, version = DubboConsts.INTERFACE_VERSION, validation = "true")
public class MasterOrderWorkModifyRemoteServiceImpl implements MasterOrderWorkModifyRemoteService {

    @Autowired
    private OrderWorkGrabBService orderWorkGrabBService;
    @Autowired
    private ZsMasterWorkBService zsMasterWorkBService;
    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private ZsNormalMasterWorkBService zsNormalMasterWorkBService;
    @Autowired
    private OrderMasterContactBService orderMasterContactBService;
    @Autowired
    private OrderWorkProgrammeBService orderWorkProgrammeBService;
    @Autowired
    private WorkFlowContextBService workFlowContextBService;
    @Autowired
    private MasterWorkService masterWorkService;
    @Autowired
    private ZsRefundBService zsRefundBService;
    @Autowired
    private ZsReworkBService zsReworkBService;
    @Autowired
    protected ZsNormalOrderBService zsNormalOrderBService;

    @Autowired
    protected OrderPayService orderPayService;

    /**
     * 工程师抢单
     *
     * @param grabOrderDIO
     * @return
     */
    @Override
    public ResponseDTO<Boolean> grabOrderWork(@NotNull(message = "入参不能为空") GrabOrderDIO grabOrderDIO) {
        log.info("【抢单】工程师抢单接口入参：【{}】", JSON.toJSONString(grabOrderDIO));
        try {
            GrabOrderWorkDTO grabOrderWorkDTO = BeanMapper.map(grabOrderDIO, GrabOrderWorkDTO.class);
            grabOrderWorkDTO.setOperator(grabOrderDIO.getMasterName());
            grabOrderWorkDTO.setOperatorId((long) grabOrderDIO.getMasterId());
            grabOrderWorkDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_MASTER);
            grabOrderWorkDTO.setGrabVersion(grabOrderDIO.getGrabVersion());
            grabOrderWorkDTO.setGrabWay(com.zmn.consts.GlobalConsts.NO);
            orderWorkGrabBService.grabOrderWork(grabOrderWorkDTO);
            return ResponseDTO.success(true, "恭喜你，抢单成功啦！");
        } catch (OmsBaseException e) {
            e.printStackTrace();
            return ResponseDTO.fail(e.getCode(), e.getMessage());
        }
    }

    @Override
    public ResponseDTO<Boolean> nonGridGrabOrderWork(GrabOrderDIO grabOrderDIO) {
        log.info("【抢单】工程师抢单接口入参：【{}】", JSON.toJSONString(grabOrderDIO));
        try {
            GrabOrderWorkDTO grabOrderWorkDTO = BeanMapper.map(grabOrderDIO, GrabOrderWorkDTO.class);
            grabOrderWorkDTO.setOperator(grabOrderDIO.getMasterName());
            grabOrderWorkDTO.setOperatorId((long)grabOrderDIO.getMasterId());
            grabOrderWorkDTO.setOperatorType(com.zmn.consts.GlobalConsts.OPERATE_USER_TYPE_MASTER);
            grabOrderWorkDTO.setGrabVersion(grabOrderDIO.getGrabVersion());
            grabOrderWorkDTO.setGrabWay(com.zmn.consts.GlobalConsts.YES);
            orderWorkGrabBService.nonGridGrabOrderWork(grabOrderWorkDTO);
            return ResponseDTO.success(true, "恭喜你，抢单成功啦！");
        } catch (OmsBaseException e) {
            e.printStackTrace();
            return ResponseDTO.fail(e.getCode(), e.getMessage());
        }
    }

    /**
     * 工程师审核订单取消
     *
     * @param cancelConfirmDIO
     * @return
     */
    @Override
    public ResponseDTO<Boolean> reviewOrderCancel(CancelConfirmDIO cancelConfirmDIO) {
        log.info("工程师审核订单取消接口入参：【{}】", JSON.toJSONString(cancelConfirmDIO));
        try {
            CancelConfirmDTO cancelConfirmDTO = BeanMapper.map(cancelConfirmDIO, CancelConfirmDTO.class);
            cancelConfirmDTO.setOperatorId((long) cancelConfirmDIO.getMasterId());
            cancelConfirmDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_MASTER);
            // 操作人
            OrderWork orderWork = orderWorkService.findOrderWorkByKey(cancelConfirmDIO.getOrderId(), cancelConfirmDIO.getWorkId());
            cancelConfirmDTO.setOperator(orderWork.getMasterName());
            cancelConfirmDTO.setOperateTime(new Date());
            zsMasterWorkBService.reviewOrderCancel(cancelConfirmDTO);
            return ResponseDTO.success();
        } catch (OmsBaseException e) {
            e.printStackTrace();
            log.info("工程师审核订单取消接口失败：{}", e);
            return ResponseDTO.fail(e.getCode(), e.getMessage());
        }
    }

    @Override
    public ResponseDTO checkComplete(OmsAppBaseDIO omsAppBaseDIO) {
        log.info("[{}]工程师完成前检查", omsAppBaseDIO.getOrderId());
        try {
            CompleteDTO completeDTO = new CompleteDTO();
            completeDTO.setWorkId(omsAppBaseDIO.getWorkId());
            completeDTO.setOrderId(omsAppBaseDIO.getOrderId());
            completeDTO.setAppPlat(omsAppBaseDIO.getAppPlat());
            completeDTO.setVersion(omsAppBaseDIO.getVersion());

            List<OrderPay> orderPays = orderPayService.listOrderPayByOrderId(completeDTO.getOrderId());
            Integer warrantyPaymentAmount = orderPays.stream()
                    .filter(x -> Objects.equals(x.getAmountType(), OrderPayConsts.ORDER_PAY_MASTER)
                            && Objects.equals(PayConsts.PAY_TRADE_TYPE_INTIME, x.getTradeType())
                            && Objects.equals(PayConsts.PAY_CHANNEL_PLATFORM_DEPOSIT, x.getPayChannelId()))
                    .mapToInt(OrderPay::getAmount).sum();

            log.info("判断是否是通过质保金支付{},{}",completeDTO.getOrderId(),warrantyPaymentAmount);
            if (NumberUtil.isNotNullOrZero(warrantyPaymentAmount)) {
                return ResponseDTO.fail("质保金支付订单，不可完成");
            }
            zsNormalMasterWorkBService.checkComplete(completeDTO);
            return ResponseDTO.success();
        } catch (OmsBaseException e) {
            return ResponseDTO.fail(e.getMessage());
        }
    }

    @Override
    public ResponseDTO telephoneSolutionCompleteOrder(ContactUserDIO contactUserDIO) {
        log.info("工程师电话解决完成工单接口入参：【{}】", JSON.toJSONString(contactUserDIO));
        try {
            ContactUserDTO userDIO = BeanMapper.map(contactUserDIO, ContactUserDTO.class);
            // 操作人
            userDIO.setOperatorId((long) userDIO.getMasterId());
            userDIO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_MASTER);
            userDIO.setOperator(contactUserDIO.getMasterName());
            orderMasterContactBService.masterTelephoneSolution(userDIO);
            // 更新完成
            CompleteDTO completeDTO = new CompleteDTO();
            completeDTO.setOrderId(contactUserDIO.getOrderId());
            completeDTO.setWorkId(contactUserDIO.getWorkId());
            completeDTO.setOperator(GlobalConsts.getOperatorTypeName(GlobalConsts.OPERATE_USER_TYPE_SYSTEM));
            completeDTO.setOperatorId((long) GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
            completeDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_SYSTEM);

            // 标记为使用配件
            OrderWork updateOrderWork = new OrderWork();
            updateOrderWork.setOrderId(contactUserDIO.getOrderId());
            updateOrderWork.setWorkId(contactUserDIO.getWorkId());
            updateOrderWork.setMasterId(contactUserDIO.getMasterId());
            updateOrderWork.setPartUse(GlobalConsts.NO);
            updateOrderWork.setPartRetain(GlobalConsts.NONE);
            masterWorkService.updateUsePart(updateOrderWork);

            // 完成
            zsNormalMasterWorkBService.completeOrder(completeDTO);
            // 发送消息
            orderWorkProgrammeBService.sendOperateInfo(completeDTO.getOrderId(), AppConsts.OPERATE_TYPE_COMPLETE);
            workFlowContextBService.asyncAutoFlow(contactUserDIO.getOrderId(), completeDTO.getWorkId());

            // 更新上门时间
            OrderWork updateVisitOrderWork = new OrderWork();
            updateVisitOrderWork.setOrderId(contactUserDIO.getOrderId());
            updateVisitOrderWork.setWorkId(contactUserDIO.getWorkId());
            updateVisitOrderWork.setVisitTime(new Date());
            masterWorkService.updateMasterVisitTime(updateVisitOrderWork);
            return ResponseDTO.success();
        } catch (Exception e) {
            log.info("workId={} 工程师电话解决完成工单失败：{}", contactUserDIO.getWorkId(), e);
            return ResponseDTO.fail(e.getMessage());
        }
    }

    @Override
    public ResponseDTO<Boolean> contactUserAgain(ContactUserDIO contactUserDIO) {
        log.info("工程师再次联系用户接口入参：【{}】", JSON.toJSONString(contactUserDIO));
        try {
            ContactUserDTO userDIO = BeanMapper.map(contactUserDIO, ContactUserDTO.class);
            orderMasterContactBService.masterContactUserAgain(userDIO);
            return ResponseDTO.success();
        } catch (Exception e) {
            e.printStackTrace();
            log.info("工程师再次联系用户接口：{}", e);
            return ResponseDTO.fail(e.getMessage());
        }
    }

    @Override
    public ResponseDTO modifyOrderWorkAddress(UpdateAddressDIO updateAddressDIO) {
        log.info("[{}]工程师修改地址入参：【{}】", updateAddressDIO.getOrderId(), JSON.toJSONString(updateAddressDIO));
        try {
            zsNormalOrderBService.modifyAddress(updateAddressDIO);
            return ResponseDTO.success();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("工程师修改地址失败：【{}】", e.getMessage());
            return ResponseDTO.fail(e.getMessage());
        }
    }

    @Override
    public ResponseDTO addRefundOrder(ReworkRefundDIO reworkRefundDIO) {
        log.info("工程师返修单建退款单接口入参：【{}】", JSON.toJSONString(reworkRefundDIO));
        try {
            zsRefundBService.addRefundOrderByEngineer(reworkRefundDIO);
            return ResponseDTO.success();
        } catch (OmsBaseException e) {
            log.error("[{}]工程师返修单建退款单接口失败：[{}]", reworkRefundDIO.getOrderId(), e.getMessage());
            return ResponseDTO.fail(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("[{}]工程师返修单建退款单接口异常：[{}]", reworkRefundDIO.getOrderId(), e);
            return ResponseDTO.fail();
        }
    }

    /**
     * 工程师返修单建返修新单
     */
    @Override
    public ResponseDTO<Long> addReworkNewOrder(OmsAppBaseDIO omsAppBaseDIO) {
        log.info("工程师返修单建返修新单接口入参：【{}】", omsAppBaseDIO);
        try {
            Long newOrderId = zsReworkBService.addReworkNewOrder(omsAppBaseDIO.getOrderId(), omsAppBaseDIO.getWorkId(), omsAppBaseDIO.getMasterId());

            return ResponseDTO.success(newOrderId);
        } catch (OmsBaseException e) {
            log.error("[{}]工程师返修单建返修新单失败：[{}]", omsAppBaseDIO.getOrderId(), e.getMessage());
            return ResponseDTO.fail(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("[{}]工程师返修单建返修新单接口异常：[{}]", omsAppBaseDIO.getOrderId(), e);
            return ResponseDTO.fail();
        }
    }
}
